home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / GNU / emacs.inst / emacs19.idb / usr / gnu / lib / emacs / site-lisp / gnus-uu.el.z / gnus-uu.el
Encoding:
Text File  |  1994-08-02  |  60.0 KB  |  1,757 lines

  1. ;;; gnus-uu.el --- extract and view or save (uu)encoded files from gnus
  2. ;;
  3. ;; Author: Lars Ingebrigtsen <larsi@ifi.uio.no>
  4. ;; Created: 2 Oct 1993
  5. ;; Version: gnus-uu.el v 1.3 1993/12/07
  6. ;; Keyword: gnus
  7. ;;
  8. ;; All gnus-uu commands start with `C-c C-v'.
  9. ;;
  10. ;; Typing `C-c C-v C-v' (gnus-uu-decode-and-view) in the summary
  11. ;; buffer will try to find all articles in the same series, uudecode
  12. ;; them and view the resulting file(s).
  13. ;;
  14. ;; gnus-uu guesses what articles are in the series according to the
  15. ;; following simple rule: The subject must be identical, except for
  16. ;; the last two numbers of the line.
  17. ;;
  18. ;; For example: If you choose a subject called "cat.gif (2/3)" gnus-uu
  19. ;; will find all the articles that matches "^cat.gif
  20. ;; ([0-9]+/[0-9]+).*$".  Subjects that are nonstandard, like "cat.gif
  21. ;; (2/3) Part 6 of a series", will not be properly recognized by 'C-c
  22. ;; C-v', and you have to mark the articles manually with '#'.
  23. ;;
  24. ;; Typing `C-c C-v v' (gnus-uu-decode-and-save) will do the same as
  25. ;; `C-c C-v C-v', except that it will not display the resulting file, but
  26. ;; save it instead.
  27. ;;
  28. ;; Typing `C-c C-v s' (gnus-uu-shar-and-save) does the same as `C-c
  29. ;; C-v v', and `C-c C-v C-s' (gnus-uu-shar-and-view) does the same as
  30. ;; `C-c C-v C-v', except that they unshar files instead, i. e. run
  31. ;; them through /bin/sh. Most shar files can be viewed and/or saved
  32. ;; with the normal uudecode commands, which is much safer, as no
  33. ;; foreign code is run.
  34. ;;
  35. ;; `#' (gnus-uu-mark-article) marks an article for later
  36. ;; decoding/unsharing/saving/viewing. The files will be decoded in the
  37. ;; sequence they were marked. To decode the files after you've marked
  38. ;; the articles you are interested in, type the corresponding key
  39. ;; strokes as the normal decoding commands, but put a `M-' in the last
  40. ;; keystroke. For instance, to perform a standard uudecode and view,
  41. ;; you would type `C-c C-v C-v'. To perform a marked uudecode and
  42. ;; view, say `C-v C-v M-C-v'. All the other view and save commands are
  43. ;; handled the same way; marked uudecode and save is then `C-c C-v
  44. ;; M-v'.
  45. ;;
  46. ;; `M-#' (gnus-uu-unmark-article) will remove the mark from a
  47. ;; previosly marked article.
  48. ;;
  49. ;; `C-c C-v C-u' (gnus-uu-unmark-all-articles) will remove the mark from
  50. ;; all marked articles.
  51. ;;
  52. ;; `C-c C-v C-r' (gnus-uu-mark-by-regexp) will prompt for a regular
  53. ;; expression and mark (forward) all articles matching that regular
  54. ;; expression.
  55. ;;
  56. ;; There's an additional way to reach the decoding functions to make
  57. ;; future expansions easier: `C-c C-v C-x'
  58. ;; (gnus-uu-multi-decode-and-view) and the corresponding save, marked
  59. ;; view and marked save keystrokes, `C-c C-v x', `C-c C-v M-C-x' and
  60. ;; `C-c C-v M-x' respectively. You will be prompted for decoding
  61. ;; method, like uudecode, shar or plain save.
  62. ;;
  63. ;; `C-c C-b' (gnus-uu-decode-and-show-in-buffer) will decode the
  64. ;; current article and display the results in an emacs buffer. This
  65. ;; might be useful if there's jsut some text in the current article
  66. ;; that has been uuencoded by some perverse poster.
  67. ;;
  68. ;; `C-c C-o' (gnus-uu-decode-and-save-all-articles) looks at all
  69. ;; unread articles in the current newsgroup and tries to uudecode
  70. ;; everything it can find. The user will be prompted for a directory
  71. ;; where the resulting files (if any) will be stored.
  72. ;;
  73. ;; `C-c C-l' (gnus-uu-edit-begin-line) lets you edit the begin line
  74. ;; of the current buffer. Useful to change an incorrect suffix or an
  75. ;; incorrect begin line.
  76. ;;
  77. ;;
  78. ;; When using the view commands, `C-c C-v C-v' for instance, gnus-uu
  79. ;; will (normally, see below) try to view the file according to the
  80. ;; rules given in gnus-uu-default-view-rules and
  81. ;; gnus-uu-user-view-rules. If it recognises the file, it will display
  82. ;; it immediately. If the file is some sort of archive, gnus-uu will
  83. ;; attempt to unpack the archive and see if any of the files in the
  84. ;; archive can be viewed. For instance, if you have a gzipped tar file
  85. ;; "pics.tar.gz" containing the files "pic1.jpg" and "pic2.gif",
  86. ;; gnus-uu will uncompress and detar the main file, and then view the
  87. ;; two pictures. This unpacking process is recursive, so if the
  88. ;; archive contains archives of archives, it'll all be unpacked.
  89. ;;
  90. ;; If the view command doesn't recognise the file type, or can't view
  91. ;; it because you don't have the viewer, or can't view *any* of the
  92. ;; files in the archive, the user will be asked if she wishes to have
  93. ;; the file saved somewhere. Note that if the decoded file is an
  94. ;; archive, and gnus-uu manages to view some of the files in the
  95. ;; archive, it won't tell the user that there were some files that
  96. ;; were unviewable. See "Interactive view" for a different approach.
  97. ;;
  98. ;;
  99. ;; Note that gnus-uu adds a function to `gnus-exit-group-hook' to
  100. ;; clear the list of marked articles and check for any generated files
  101. ;; that might have escaped deletion if the user typed `C-g'.
  102. ;;
  103. ;;
  104. ;; `C-c C-v C-a' (gnus-uu-toggle-asynchronous) toggles the
  105. ;; gnus-uu-asynchronous variable. See below for explanation.
  106. ;;
  107. ;; `C-c C-v C-q' (gnus-uu-toggle-query) toggles the
  108. ;; gnus-uu-ask-before-view variable. See below for explanation.
  109. ;;
  110. ;; `C-c C-v C-p' (gnus-uu-toggle-always-ask) toggles the
  111. ;; gnus-uu-view-and-save variable. See below for explanation.
  112. ;;
  113. ;; `C-c C-v C-k' (gnus-uu-toggle-kill-carriage-return) toggles the
  114. ;; gnus-uu-kill-carriage-return variable. See below for explanation.
  115. ;;
  116. ;; `C-c C-v C-i' (gnus-uu-toggle-interactive-view) toggles interactive
  117. ;; mode. If it is turned on, gnus-uu won't view files immediately but
  118. ;; give you a buffer with the default commands and files and lets you
  119. ;; edit the commands and execute them at leisure.
  120. ;;
  121. ;; `C-c C-v C-t' (gnus-uu-toggle-any-variable) is an interface to the
  122. ;; five toggle commands listed above.
  123. ;;
  124. ;;
  125. ;; Customization
  126. ;;
  127. ;; To load this file when starting gnus, put sumething like the
  128. ;; following in your .emacs file:
  129. ;;
  130. ;;   (setq gnus-group-mode-hook
  131. ;;      '(lambda () (load "gnus-uu")))
  132. ;;
  133. ;; To make gnus-uu use, for instance, "xli" to view JPEGs and GIFs,
  134. ;; put this in your .emacs file:
  135. ;;
  136. ;;   (setq gnus-uu-user-view-rules 
  137. ;;     (list
  138. ;;      '("jpg$\\|gif$" "xli") 
  139. ;;      ))
  140. ;;
  141. ;; This variable is a list where each list item is a list containing
  142. ;; two strings. The first string is a regular expression. If the file
  143. ;; name is matched by this expression, the command given in the
  144. ;; second string is executed on this file. If the command contains
  145. ;; "%s", the file will be inserted there in the command string. Eg.
  146. ;; "giftoppm %s | xv -" will result in the file name being inserted at
  147. ;; the "%s".
  148. ;;
  149. ;; If you don't want to display certain file types, like if you
  150. ;; haven't got sound capabilities, you could put something like
  151. ;;
  152. ;;   (setq gnus-uu-user-view-rules 
  153. ;;     (list
  154. ;;      '("au$\\|voc$\\|wav$" nil) 
  155. ;;      ))
  156. ;;
  157. ;; in your .emacs file.
  158. ;;
  159. ;; There's a similar variable called 'gnus-uu-user-archive-rules'
  160. ;; which gives a list of unarcers to use when looking inside archives
  161. ;; for files to display.
  162. ;;
  163. ;; If you don't want gnus-uu to look inside archives for files to
  164. ;; display, say
  165. ;;
  166. ;;   (setq gnus-uu-do-not-unpack-archives t)
  167. ;;
  168. ;;
  169. ;; If you want gnus-uu to ask you if you want to save a file after
  170. ;; viewing, say
  171. ;;
  172. ;;   (setq gnus-uu-view-and-save t)
  173. ;;
  174. ;;
  175. ;; If you don't want to wait for the viewing command to finish before
  176. ;; returning to emacs, say
  177. ;;
  178. ;;   (setq gnus-uu-asynchronous t)
  179. ;;
  180. ;;
  181. ;; This can be useful if you're viewing long .mod files, for instance,
  182. ;; which often takes several minutes. Note, however, that since
  183. ;; gnus-uu doesn't ask, and if you are viewing an archive with lots of
  184. ;; viewable files, you'll get them all up more or less at once, which
  185. ;; can be confusing, to say the least. To get gnus-uu to ask you
  186. ;; before viewing a file, say
  187. ;;
  188. ;;   (setq gnus-uu-ask-before-view t)
  189. ;;
  190. ;; You can set this variable even if you're not using asynchronous
  191. ;; viewing, of course.
  192. ;;
  193. ;; If the articles has been posted by some numbscull with a PC (isn't
  194. ;; that a bit redundant, though?) and there's lots of carriage returns
  195. ;; everywhere, say
  196. ;;
  197. ;;   (setq gnus-uu-kill-carriage-return t)
  198. ;;
  199. ;; If you want gnus-uu to ignore the default file rules when viewing,
  200. ;; for instance if there's several file types that you can't view, set
  201. ;; `gnus-uu-ignore-default-view-rules' to `t'. There's a similar
  202. ;; variable to disable the default unarchive rule list,
  203. ;; `gnus-uu-ignore-default-archive-rules'.
  204. ;;
  205. ;; If you want a more interactive approach to file viewing, say
  206. ;;
  207. ;;   (setq gnus-uu-use-interactive-view t)
  208. ;;
  209. ;; If this variable is set, whenever you type `C-c C-v C-v' (or any of
  210. ;; the other view commands), gnus-uu will present you with a buffer
  211. ;; with the default actions and file names after decoding. You can
  212. ;; edit the command lines and execute them in a convenient fashion.
  213. ;; The output from the commands will be displayed in a small window at
  214. ;; the bottom of the emacs window. End interactive mode by typing `C-c
  215. ;; C-c' in the view window.
  216. ;;
  217. ;; If you want gnus-uu to unmark articles that you have asked to
  218. ;; decode, but can't be decoded (if, for instance, the articles aren't
  219. ;; uuencoded files or the posting is incomplete), say
  220. ;;
  221. ;;   (setq gnus-uu-unmark-articles-not-decoded t)
  222. ;;
  223. ;;
  224. ;; History
  225. ;;
  226. ;; v1.0: First version released Oct 2 1992.
  227. ;;
  228. ;; v1.1: Changed `C-c C-r' to `C-c C-e' and `C-c C-p' to `C-c C-k'.
  229. ;; Changed (setq gnus-exit-group-hook) to (add-hook).  Removed
  230. ;; checking for "Re:" for finding parts.
  231. ;;
  232. ;; v2.2: Fixed handling of currupted archives. Changed uudecoding to
  233. ;; an asynchronous process to avoid loading tons of data into emacs
  234. ;; buffers. No longer reads articles emacs already have aboard.  Fixed
  235. ;; a firmer support for shar files. Made regexp searches for files
  236. ;; more convenient. Added `C-c C-l' for editing uucode begin
  237. ;; lines. Added multi-system decoder entry point. Added interactive
  238. ;; view mode. Added function for decoding and saving all uuencoded
  239. ;; articles in the current newsgroup.
  240. ;;
  241. ;; v2.3: After suggestions I have changed all the gnus-uu key bindings
  242. ;; to avoid hogging all the user keys (C-c LETTER). Also added
  243. ;; (provide) and fixed some saving stuff. First posted version to
  244. ;; gnu.emacs.sources. 
  245. ;;
  246. ;;
  247. ;; Keymap overview:
  248. ;; 
  249. ;; All commands start with `C-c C-v'. The difference is in the third
  250. ;; keystroke.  All view commands are `C-LETTER'. All save commands are
  251. ;; just `LETTER'. All marked commands are the same as the unmarked
  252. ;; commands, except that they have `M-' before in the last keystroke.
  253. ;;
  254. ;; `C-c C-v C-v'         gnus-uu-decode-and-view
  255. ;; `C-c C-v v'           gnus-uu-decode-and-save
  256. ;; `C-c C-v C-s'         gnus-uu-shar-and-view
  257. ;; `C-c C-v s'           gnus-uu-shar-and-save
  258. ;; `C-c C-v C-m'         gnus-uu-multi-decode-and-view
  259. ;; `C-c C-v m'           gnus-uu-multi-decode-and-save
  260. ;;
  261. ;; `C-c C-v C-b'         gnus-uu-decode-and-show-in-buffer
  262. ;; `C-c C-v a'           gnus-uu-decode-and-save-all-articles
  263. ;; `C-c C-v C-l'         gnus-uu-edit-begin-line
  264. ;;
  265. ;; `#'                   gnus-uu-mark-article
  266. ;; `M-#'                 gnus-uu-unmark-article
  267. ;; `C-c C-v C-u'         gnus-uu-unmark-all-articles
  268. ;; `C-c C-v C-r'         gnus-uu-mark-by-regexp
  269. ;; `C-c C-v M-C-v'       gnus-uu-marked-decode-and-view
  270. ;; `C-c C-v M-v'         gnus-uu-marked-decode-and-save
  271. ;; `C-c C-v M-C-s'       gnus-uu-marked-shar-and-view
  272. ;; `C-c C-v M-s'         gnus-uu-marked-shar-and-save
  273. ;; `C-c C-v M-C-m'       gnus-uu-marked-multi-decode-and-view
  274. ;; `C-c C-v M-m'         gnus-uu-marked-multi-decode-and-save
  275. ;;
  276. ;; `C-c C-v C-a'         gnus-uu-toggle-asynchronous
  277. ;; `C-c C-v C-q'         gnus-uu-toggle-query
  278. ;; `C-c C-v C-p'         gnus-uu-toggle-always-ask
  279. ;; `C-c C-v C-k'         gnus-uu-toggle-kill-carriage-return
  280. ;; `C-c C-v C-i'         gnus-uu-toggle-interactive-view
  281. ;; `C-c C-v C-t'         gnus-uu-toggle-any-variable
  282.  
  283. (require 'gnus)
  284.  
  285. ;; Binding of keys to the gnus-uu functions.
  286.  
  287. (defvar gnus-uu-ctl-map nil)
  288. (define-prefix-command 'gnus-uu-ctl-map)
  289. (define-key gnus-summary-mode-map "\C-c\C-v" gnus-uu-ctl-map)
  290.  
  291. (define-key gnus-uu-ctl-map "\C-v" 'gnus-uu-decode-and-view)
  292. (define-key gnus-uu-ctl-map "v" 'gnus-uu-decode-and-save)
  293. (define-key gnus-uu-ctl-map "\C-s" 'gnus-uu-shar-and-view)
  294. (define-key gnus-uu-ctl-map "s" 'gnus-uu-shar-and-save)
  295. (define-key gnus-uu-ctl-map "\C-m" 'gnus-uu-multi-decode-and-view)
  296. (define-key gnus-uu-ctl-map "m" 'gnus-uu-multi-decode-and-save)
  297.  
  298. (define-key gnus-uu-ctl-map "\C-b" 'gnus-uu-decode-and-show-in-buffer)
  299.  
  300. (define-key gnus-summary-mode-map "#" 'gnus-uu-mark-article)
  301. (define-key gnus-summary-mode-map "\M-#" 'gnus-uu-unmark-article)
  302. (define-key gnus-uu-ctl-map "\C-u" 'gnus-uu-unmark-all-articles)
  303. (define-key gnus-uu-ctl-map "\C-r" 'gnus-uu-mark-by-regexp)
  304.  
  305. (define-key gnus-uu-ctl-map "\M-\C-v" 'gnus-uu-marked-decode-and-view)
  306. (define-key gnus-uu-ctl-map "\M-v" 'gnus-uu-marked-decode-and-save)
  307. (define-key gnus-uu-ctl-map "\M-\C-s" 'gnus-uu-marked-shar-and-view)
  308. (define-key gnus-uu-ctl-map "\M-s" 'gnus-uu-marked-shar-and-save)
  309. (define-key gnus-uu-ctl-map "\M-\C-m" 'gnus-uu-marked-multi-decode-and-view)
  310. (define-key gnus-uu-ctl-map "\M-m" 'gnus-uu-marked-multi-decode-and-save)
  311.  
  312. (define-key gnus-uu-ctl-map "\C-a" 'gnus-uu-toggle-asynchronous)
  313. (define-key gnus-uu-ctl-map "\C-q" 'gnus-uu-toggle-query)
  314. (define-key gnus-uu-ctl-map "\C-p" 'gnus-uu-toggle-always-ask)
  315. (define-key gnus-uu-ctl-map "\C-k" 'gnus-uu-toggle-kill-carriage-return)
  316. (define-key gnus-uu-ctl-map "\C-i" 'gnus-uu-toggle-interactive-view)
  317. (define-key gnus-uu-ctl-map "\C-t" 'gnus-uu-toggle-any-variable)
  318.  
  319. (define-key gnus-uu-ctl-map "\C-l" 'gnus-uu-edit-begin-line)
  320.  
  321. (define-key gnus-uu-ctl-map "a" 'gnus-uu-decode-and-save-all-articles)
  322.  
  323.  
  324. ;; Default viewing actions
  325.  
  326. (defconst gnus-uu-default-view-rules 
  327.   (list '("\\.\\(jpe?g$\\|gif$\\|tiff?$\\|p[pgb]m$\\|xwd$\\|xbm$\\)" "xv")
  328.     '("\\.txt$\\|\\.doc$\\|read.*me" "xterm -e less")
  329.     '("\\.fli$" "xflick")
  330.     '("\\.\\(wav\\|aiff\\|hcom\\|u[blw]\\|s[bfw]\\|voc\\|smp\\)$" 
  331.       "sox %s -t .au - > /dev/audio")
  332.     '("\\.au$" "cat %s > /dev/audio")
  333.     '("\\.mod$" "str32")
  334.     '("\\.ps$" "ghostview")
  335.     '("\\.dvi$" "xdvi")
  336.     '("\\.1$" "xterm -e man -l")
  337.     '("\\.html$" "xmosaic")
  338.     '("\\.mpe?g$" "mpeg_play")
  339.     '("\\.\\(tar\\|arj\\|zip\\|zoo\\|arc\\|gz\\|Z\\|lzh\\|ar\\)$" 
  340.       "gnus-uu-archive"))
  341.  
  342.  
  343.   "This constant is a list that gives the default actions to be taken
  344. when the user asks to view a file. To change the behaviour, you can
  345. either edit this constant or set 'gnus-uu-user-view-rules' to 
  346. something useful. To add a default \"end\" rule, edit the
  347. 'gnus-uu-user-view-rules-end' variable.
  348.  
  349. For example:
  350.  
  351. To make gnus-uu use 'xli' to display JPEG and GIF files, put the following in
  352. your .emacs file
  353.  
  354.   (setq gnus-uu-user-view-rules (list '(\"jpg$\\\\|gif$\" \"xli\")))
  355.  
  356. Both these variables are lists of lists of strings, where the first string
  357. is a regular expression. If the file name matches this regular expression,
  358. the command in the second string is fed the file.
  359.  
  360. If the command string contains \"%s\", the file name will be inserted
  361. at that point in the command string. If there's no \"%s\" in the command
  362. string, the file name will be appended to the command before executing.
  363. ")
  364.  
  365. (defvar gnus-uu-user-view-rules nil 
  366. "User variable. See explanation of the 'gnus-uu-default-view-rules' for 
  367. details.")
  368. (defvar gnus-uu-user-view-rules-end nil)
  369.  
  370.  
  371. ;; Default unpacking commands
  372.  
  373. (defconst gnus-uu-default-archive-rules 
  374.   (list '("\\.tar$" "tar xf")
  375.     '("\\.zip$" "unzip")
  376.     '("\\.ar$" "ar x")
  377.     '("\\.arj$" "unarj x")
  378.     '("\\.zoo$" "zoo -e")
  379.     '("\\.lzh$" "lha x")
  380.     '("\\.Z$" "uncompress")
  381.     '("\\.gz$" "gunzip")
  382.     '("\\.arc$" "arc -x"))
  383.   "*")
  384. (defvar gnus-uu-user-archive-rules nil)
  385.  
  386.  
  387. ;; Various variables
  388.  
  389. (defconst gnus-uu-tmp-dir "/tmp/" 
  390.   "Variable saying where gnus-uu is to do its work.")
  391.  
  392. (defconst gnus-uu-output-buffer-name "*Gnus UU Output*" "*")
  393. (defconst gnus-uu-result-buffer "*Gnus UU Result Buffer*" "*")
  394.  
  395. (defvar gnus-uu-marked-article-list nil "*")
  396.  
  397. (defvar gnus-uu-do-not-unpack-archives nil 
  398.   "Set this variable if you don't want gnus-uu to look inside
  399. archives for files to display.")
  400.  
  401. (defvar gnus-uu-view-and-save nil 
  402.   "Set this variable if you want to be asked if you want to save the
  403. file after viewing. If this variable is nil, which is the default, 
  404. gnus-uu won't offer to save a file if viewing is successful.")
  405.  
  406. (defvar gnus-uu-asynchronous nil
  407.   "Set this variable to `t' if you don't want gnus-uu to wait until 
  408. the viewing command has ended before returning control to emacs.")
  409. (defvar gnus-uu-ask-before-view nil
  410.   "Set this variable to `t' if you want gnus-uu to ask you before 
  411. viewing every file. Useful when `gnus-uu-asynchronous' is set.")
  412.  
  413. (defvar gnus-uu-ignore-default-view-rules nil
  414.   "Set this variable if you want gnus-uu to ignore the default viewing
  415. rules and just use the rules given in gnus-uu-user-view-rules.")
  416.  
  417. (defvar gnus-uu-ignore-default-archive-rules nil
  418.   "Set this variable if you want gnus-uu to ignore the default archive
  419. unpacking commands and just use the rules given in 
  420. gnus-uu-user-archive-rules.")
  421.  
  422. (defvar gnus-uu-kill-carriage-return nil
  423.   "Set this variable if you want to remove all carriage returns from
  424. the mail articles.")
  425.  
  426. (defvar gnus-uu-generated-file-list nil)
  427.  
  428. (defconst gnus-uu-uudecode-process nil)
  429.  
  430. ;; Definition of uuencoded body etc.
  431.  
  432. (defconst gnus-uu-begin-string "^begin[ \t]+[0-7][0-7][0-7][ \t]+\\(.*\\)$" 
  433.   "*")
  434. (defconst gnus-uu-end-string "^end[ \t]*$")
  435. (defconst gnus-uu-body-line
  436. "^M.............................................................?$" "*")
  437. (defconst gnus-uu-shar-begin-string "^#! */bin/sh" "*")
  438.  
  439. (defvar gnus-uu-file-name nil)
  440.  
  441. (defvar gnus-uu-shar-file-name nil "*")
  442. (defconst gnus-uu-shar-name-marker "begin [0-7][0-7][0-7][ \t]+\\(\\(\\w\\|\\.\\)*\\b\\)" "*")
  443. (defvar gnus-uu-shar-directory nil)
  444.  
  445. (defvar gnus-uu-use-interactive-view nil)
  446. (defvar gnus-uu-interactive-file-list nil)
  447. (defconst gnus-uu-interactive-buffer-name "*gnus-uu interactive*")
  448.  
  449. (defvar gnus-uu-unmark-articles-not-decoded nil)
  450.  
  451. (defvar gnus-uu-output-window-height 14 
  452.   "This variable says how hight the output buffer window is to be when
  453. using interactive view mode. Change it at your convenience.")
  454.  
  455. ;; Interactive functions
  456.  
  457.  
  458. (defun gnus-uu-decode-and-view ()
  459.   "UUdecodes and 'views' (if possible) the resulting file.
  460. 'Viewing' can be any action at all, as defined in the 
  461. 'gnus-uu-file-action-list' variable. Running 'xv' on gifs and
  462. 'play' on au files are popular actions. If the file can't be viewed,
  463. the user is asked if she would like to save the file instead."
  464.   (interactive)
  465.   (gnus-uu-decode-and-view-or-save t nil))
  466.  
  467. (defun gnus-uu-decode-and-save ()
  468.   "uudecodes and saves the resulting file."
  469.   (interactive)
  470.   (gnus-uu-decode-and-view-or-save nil nil))
  471.  
  472. (defun gnus-uu-marked-decode-and-view ()
  473.   "The marked equivalent to gnus-uu-decode-and-view."
  474.   (interactive)
  475.   (gnus-uu-decode-and-view-or-save t t))
  476.  
  477. (defun gnus-uu-marked-decode-and-save ()
  478.   "The marked equivalent to gnus-uu-decode-and-save."
  479.   (interactive)
  480.   (gnus-uu-decode-and-view-or-save nil nil))
  481.       
  482.  
  483. (defun gnus-uu-shar-and-view ()
  484.   "Does the same as gnus-uu-decode-and-view for shar files."
  485.   (interactive)
  486.   (gnus-uu-unshar-and-view-or-save t nil))
  487.  
  488. (defun gnus-uu-shar-and-save ()
  489.   "Does the same as gnus-uu-decode-and-save for shar files."
  490.   (interactive)
  491.   (gnus-uu-unshar-and-view-or-save nil nil))
  492.  
  493. (defun gnus-uu-marked-shar-and-view ()
  494.   "The marked equivalent to gnus-uu-shar-and-view."
  495.   (interactive)
  496.   (gnus-uu-unshar-and-view-or-save t t))
  497.  
  498. (defun gnus-uu-marked-shar-and-save ()
  499.   "The marked equivalent to gnus-uu-shar-and-save."
  500.   (interactive)
  501.   (gnus-uu-unshar-and-view-or-save nil t))
  502.  
  503.  
  504. (defun gnus-uu-decode-and-show-in-buffer ()
  505.   "uudecodes the current article and displays the result in a buffer."
  506.   (interactive)
  507.   (let ((uu-buffer (get-buffer-create gnus-uu-output-buffer-name))
  508.     list-of-articles file-name)
  509.     (save-excursion
  510.   
  511.     (and (setq list-of-articles (list gnus-current-article))
  512.      (gnus-uu-grab-articles list-of-articles 'gnus-uu-uustrip-article-as)
  513.      (setq file-name (gnus-uu-decode gnus-uu-tmp-dir))
  514.      (progn
  515.        (save-excursion
  516.          (set-buffer uu-buffer)
  517.          (erase-buffer)
  518.          (insert-file-contents file-name))
  519.        (set-window-buffer (get-buffer-window gnus-article-buffer) 
  520.                   uu-buffer)
  521.        (message (format "Showing file %s in buffer" file-name))
  522.        (delete-file file-name))))))
  523.       
  524.  
  525. (defun gnus-uu-toggle-asynchronous ()
  526.   "This function toggles asynchronous viewing."
  527.   (interactive)
  528.   (if (setq gnus-uu-asynchronous (not gnus-uu-asynchronous))
  529.       (message "gnus-uu will now view files asynchronously")
  530.     (message "gnus-uu will now view files synchronously")))
  531.  
  532. (defun gnus-uu-toggle-query ()
  533.   "This function toggles whether to ask before viewing or not."
  534.   (interactive)
  535.   (if (setq gnus-uu-ask-before-view (not gnus-uu-ask-before-view))
  536.       (message "gnus-uu will now ask before viewing")
  537.     (message "gnus-uu will now view without asking first")))
  538.  
  539. (defun gnus-uu-toggle-always-ask ()
  540.   "This function toggles whether to ask saving a file even after successful
  541. viewing."
  542.   (interactive)
  543.   (if (setq gnus-uu-view-and-save (not gnus-uu-view-and-save))
  544.       (message "gnus-uu will now ask to save the file after viewing")
  545.     (message "gnus-uu will now not ask to save after successful viewing")))
  546.  
  547. (defun gnus-uu-toggle-interactive-view ()
  548.   "This function toggles whether to use interactive view."
  549.   (interactive)
  550.   (if (setq gnus-uu-use-interactive-view (not gnus-uu-use-interactive-view))
  551.       (message "gnus-uu will now use interactive view")
  552.     (message "gnus-uu will now use non-interactive view")))
  553.  
  554. (defun gnus-uu-toggle-unmark-undecoded ()
  555.   "This function toggles whether to unmark articles not decoded."
  556.   (interactive)
  557.   (if (setq gnus-uu-unmark-articles-not-decoded 
  558.         (not gnus-uu-unmark-articles-not-decoded))
  559.       (message "gnus-uu will now unmark articles not decoded")
  560.     (message "gnus-uu will now not unmark articles not decoded")))
  561.  
  562. (defun gnus-uu-toggle-kill-carriage-return ()
  563.   "This function toggles the stripping of carriage returns from the articles."
  564.   (interactive)
  565.   (if (setq gnus-uu-kill-carriage-return (not gnus-uu-kill-carriage-return))
  566.       (message "gnus-uu will now strip carriage returns")
  567.     (message "gnus-uu won't strip carriage returns")))
  568.  
  569. (defun gnus-uu-toggle-any-variable ()
  570.   "This function ask what variable the user wants to toggle."
  571.   (interactive)
  572.   (let (rep)
  573.     (message "(a)sync, (q)uery, (p)always ask, (k)ill carriage, (i)nteractive, (u)nmark")
  574.     (setq rep (read-char))
  575.     (if (= rep ?a)
  576.     (gnus-uu-toggle-asynchronous))
  577.     (if (= rep ?q)
  578.     (gnus-uu-toggle-query))
  579.     (if (= rep ?y)
  580.     (gnus-uu-toggle-always-ask))
  581.     (if (= rep ?c)
  582.     (gnus-uu-toggle-kill-carriage-return))
  583.     (if (= rep ?u)
  584.     (gnus-uu-toggle-unmark-undecoded))
  585.     (if (= rep ?t)
  586.     (gnus-uu-toggle-interactive-view))))
  587.  
  588.  
  589. (defun gnus-uu-edit-begin-line ()
  590.   "Edit the begin line of the current article."
  591.   (interactive)
  592.   (let (begin b buffer-read-only)
  593.     (save-excursion
  594.       (set-buffer gnus-article-buffer)
  595.       (goto-line 1)
  596.       (if (not (re-search-forward gnus-uu-begin-string nil t))
  597.       (progn (message "No begin line in the current article") (sit-for 2))
  598.     (beginning-of-line)
  599.     (setq b (point))
  600.     (end-of-line)
  601.     (setq begin (buffer-substring b (point)))
  602.     (setq begin (read-string "" begin))
  603.     (setq buffer-read-only nil)
  604.     (delete-region b (point))
  605.     (insert-string begin)))))
  606.  
  607. ;; Multi functions
  608.  
  609. (defun gnus-uu-multi-decode-and-view ()
  610.   "This function lets the user decide what method to use for decoding.
  611. Other than that, it's equivalent to the other decode-and-view functions."
  612.   (interactive)
  613.   (gnus-uu-multi-decode-and-view-or-save t nil))
  614.  
  615. (defun gnus-uu-multi-decode-and-save ()
  616.   "This function lets the user decide what method to use for decoding.
  617. Other than that, it's equivalent to the other decode-and-save functions."
  618.   (interactive)
  619.   (gnus-uu-multi-decode-and-view-or-save nil nil))
  620.  
  621. (defun gnus-uu-marked-multi-decode-and-view ()
  622.   "This function lets the user decide what method to use for decoding.
  623. Other than that, it's equivalent to the other marked decode-and-view 
  624. functions."
  625.   (interactive)
  626.   (gnus-uu-multi-decode-and-view-or-save t t))
  627.  
  628. (defun gnus-uu-marked-multi-decode-and-save ()
  629.   "This function lets the user decide what method to use for decoding.
  630. Other than that, it's equivalent to the other marked decode-and-save 
  631. functions."
  632.   (interactive)
  633.   (gnus-uu-multi-decode-and-view-or-save t t))
  634.  
  635. (defun gnus-uu-multi-decode-and-view-or-save (view marked)
  636.   (let (decode-type)
  637.     (message "(u)udecode, (s)har, s(a)ve: ")
  638.     (setq decode-type (read-char))
  639.     (if (= decode-type ?
  640. ) (setq decode-type ?u))
  641.     (if (= decode-type ?u)
  642.     (gnus-uu-decode-and-view-or-save view marked)
  643.       (if (= decode-type ?s)
  644.       (gnus-uu-unshar-and-view-or-save view marked)
  645.     (if (= decode-type ?a)
  646.         (gnus-uu-save-articles view marked)
  647.       (message (format "Unknown decode method '%c'." decode-type))
  648.       (sit-for 2))))))
  649.  
  650. ;; All files
  651. (defconst gnus-uu-rest-of-articles nil)
  652. (defconst gnus-uu-do-sloppy-uudecode nil)
  653. (defvar gnus-uu-current-save-dir nil "*")
  654.  
  655. (defun gnus-uu-decode-and-save-all-articles ()
  656.   "This function reads all unread aticles in the current group and
  657. sees whether it can uudecode the articles. The user will be prompted
  658. for an directory to put the resulting (if any) files."
  659.   (interactive)
  660.   (let ((gnus-uu-unmark-articles-not-decoded t)
  661.     where dir did unmark)
  662.     (setq gnus-uu-do-sloppy-uudecode t)
  663.     (setq dir (gnus-uu-read-directory "Where do you want the files? "
  664.            gnus-uu-current-save-dir))
  665.     (setq gnus-uu-current-save-dir dir)
  666.     (setq gnus-uu-rest-of-articles (gnus-uu-get-list-of-articles "^." t t))
  667.     (setq gnus-uu-file-name nil)
  668.     (while (and gnus-uu-rest-of-articles 
  669.         (gnus-uu-grab-articles gnus-uu-rest-of-articles 
  670.                        'gnus-uu-uustrip-article-as))
  671.       (if gnus-uu-file-name
  672.       (progn
  673.         (rename-file (concat gnus-uu-tmp-dir gnus-uu-file-name) 
  674.              (concat dir gnus-uu-file-name) t)
  675.         (setq did t)
  676.         (setq gnus-uu-file-name nil))))
  677.     (if did (message "Saved.")))
  678.   (setq gnus-uu-do-sloppy-uudecode nil))
  679.  
  680.  
  681.  
  682. ;; Work functions
  683.  
  684. (defun gnus-uu-decode-and-view-or-save (view marked)
  685.   (gnus-uu-initialize)
  686.   (let (file decoded)
  687.     (save-excursion
  688.       (if (gnus-uu-decode-and-strip nil marked)
  689.       (progn
  690.         (setq decoded t)
  691.         (setq file (concat gnus-uu-tmp-dir gnus-uu-file-name))
  692.         (if view (gnus-uu-view-file file)
  693.           (gnus-uu-save-file file)))))
  694.  
  695.     (gnus-summary-next-subject 1 t)
  696.  
  697.     (if (and gnus-uu-use-interactive-view view decoded)
  698.     (gnus-uu-do-interactive))
  699.  
  700.     (if (or (not gnus-uu-use-interactive-view) (not decoded))
  701.     (gnus-uu-clean-up))))
  702.  
  703.     
  704. (defun gnus-uu-unshar-and-view-or-save (view marked)
  705.   "Unshars and views/saves marked/unmarked articles."
  706.   (gnus-uu-initialize)
  707.   (let (tar-file files decoded)
  708.     (save-excursion
  709.       (setq gnus-uu-shar-directory 
  710.         (make-temp-name (concat gnus-uu-tmp-dir "gnusuush")))
  711.       (make-directory gnus-uu-shar-directory)
  712.       (gnus-uu-add-file gnus-uu-shar-directory)
  713.       (if (gnus-uu-decode-and-strip t marked)
  714.       (progn
  715.         (setq decoded t)
  716.         (setq files (directory-files gnus-uu-shar-directory t))
  717.         (setq gnus-uu-generated-file-list
  718.           (append files gnus-uu-generated-file-list))
  719.         (if (> (length files) 3)
  720.         (progn 
  721.           (setq tar-file 
  722.             (concat
  723.              (make-temp-name (concat gnus-uu-tmp-dir "gnusuuar"))
  724.              ".tar"))
  725.           (gnus-uu-add-file tar-file)
  726.           (call-process "sh" nil 
  727.                 (get-buffer-create gnus-uu-output-buffer-name)
  728.                 nil "-c" 
  729.                 (format "cd %s ; tar cf %s * ; cd .. ; rm -r %s" 
  730.                     gnus-uu-shar-directory 
  731.                     tar-file
  732.                     gnus-uu-shar-directory))
  733.           (if view
  734.               (gnus-uu-view-file tar-file)
  735.             (gnus-uu-save-file tar-file)))
  736.           (if view
  737.           (gnus-uu-view-file (elt files 2))
  738.         (gnus-uu-save-file (elt files 2)))))))
  739.  
  740.     (gnus-summary-next-subject 1 t)
  741.  
  742.     (if (and gnus-uu-use-interactive-view view decoded)
  743.     (gnus-uu-do-interactive))
  744.  
  745.     (if (or (not gnus-uu-use-interactive-view) (not decoded))
  746.     (gnus-uu-clean-up))))
  747.  
  748.  
  749.  
  750. (defconst gnus-uu-saved-article-name nil)
  751. (defun gnus-uu-save-articles (view marked)
  752.   (let (list-of-articles)
  753.     (save-excursion
  754.       (if (not marked)
  755.       (setq list-of-articles (gnus-uu-get-list-of-articles))
  756.     (setq list-of-articles (reverse gnus-uu-marked-article-list))
  757.     (setq gnus-uu-marked-article-list nil))
  758.       (if (not list-of-articles)
  759.       (progn
  760.         (message "No list of articles")
  761.         (sit-for 2))
  762.     (setq gnus-uu-saved-article-name 
  763.           (concat gnus-uu-tmp-dir 
  764.               (read-file-name "Enter file name: " gnus-newsgroup-name
  765.                       gnus-newsgroup-name)))
  766.     (gnus-uu-add-file gnus-uu-saved-article-name)
  767.     (if (gnus-uu-grab-articles list-of-articles 'gnus-uu-save-article)
  768.         (gnus-uu-save-file gnus-uu-saved-article-name))
  769.     ))))
  770.  
  771. (defun gnus-uu-save-article (buffer in-state)
  772.   (save-excursion
  773.     (set-buffer buffer)
  774.     (call-process-region 
  775.      1 (point-max) "sh" nil (get-buffer-create gnus-uu-output-buffer-name)
  776.      nil "-c" (concat "cat >> " gnus-uu-saved-article-name)))
  777.   'ok)
  778.  
  779. (defun gnus-uu-view-file (file-name &optional dont-ask)
  780.   "This function takes two parameters. The first is name of the file to be 
  781. viewed. gnus-uu-view-file will look for an action associated with the file
  782. type of the file. If it finds an appropriate action, the file will be
  783. attempted displayed.
  784.  
  785. The second parameter specifies if the user is to be asked whether to
  786. save the file if viewing is unsuccessful. `t' means 'do not ask.'
  787.  
  788. Note that the file given will be deleted by this function, one way or
  789. another. If `gnus-uu-asynchronous' is set, it won't be deleted right
  790. away, but sometime later. If the user is offered to save the file, it'll
  791. be moved to wherever the user wants it. 
  792.  
  793. gnus-uu-view-file returns `t' if viewing is successful."
  794.   (let (action did-view
  795.     (didnt-want t)
  796.     (do-view t))
  797.     (setq action (gnus-uu-choose-action
  798.           file-name
  799.           (append gnus-uu-user-view-rules 
  800.               (if gnus-uu-ignore-default-view-rules 
  801.                   nil 
  802.                 gnus-uu-default-view-rules)
  803.               gnus-uu-user-view-rules-end)))
  804.  
  805.     (if (and gnus-uu-use-interactive-view 
  806.          (not (string= (or action "") "gnus-uu-archive")))
  807.     (gnus-uu-enter-interactive-file (or action "") file-name)
  808.  
  809.       (if action
  810.       (if (string= action "gnus-uu-archive") 
  811.           (setq did-view (gnus-uu-treat-archive file-name))
  812.       
  813.         (if gnus-uu-ask-before-view
  814.         (setq didnt-want 
  815.               (or (not 
  816.                (setq do-view
  817.                  (y-or-n-p 
  818.                   (format "Do you want to view %s? " 
  819.                       file-name))))
  820.               didnt-want)))
  821.  
  822.         (if do-view
  823.         (setq did-view 
  824.               (if gnus-uu-asynchronous
  825.               (gnus-uu-call-asynchronous file-name action)
  826.             (gnus-uu-call-synchronous file-name action))))))
  827.  
  828.       (if (and (not dont-ask) (not gnus-uu-use-interactive-view))
  829.       (progn
  830.         (if (and
  831.          didnt-want
  832.          (or (not action)
  833.              (and (string= action "gnus-uu-archive") (not did-view))))
  834.         (progn
  835.           (message (format "Could find no rule for %s" file-name))
  836.           (sit-for 2)))
  837.         (and (or (not did-view) gnus-uu-view-and-save)
  838.          (y-or-n-p 
  839.           (format "Do you want to save the file %s? " file-name))
  840.          (gnus-uu-save-file file-name))))
  841.  
  842.       (if (and (file-exists-p file-name) 
  843.            (not gnus-uu-use-interactive-view)
  844.            (or 
  845.         (not (and gnus-uu-asynchronous did-view))
  846.         (string= action "gnus-uu-archive")))
  847.       (delete-file file-name)))
  848.  
  849.     did-view))
  850.  
  851.  
  852. (defun gnus-uu-call-synchronous (file-name action)
  853.   "Takes two parameters: The name of the file to be displayed and
  854. the command to display it with. Returns `t' on success and `nil' if
  855. the file couldn't be displayed."
  856.   (let (did-view command)
  857.     (save-excursion
  858.       (set-buffer (get-buffer-create gnus-uu-output-buffer-name))
  859.       (erase-buffer)
  860.       (if (string-match "%s" action)
  861.       (setq command (format action file-name))
  862.     (setq command (concat action " " file-name)))
  863.       (message (format "Viewing with '%s'" command))
  864.       (if (not (= 0 (call-process "sh" nil t nil "-c" command)))
  865.       (progn
  866.         (goto-char 1)
  867.         (while (re-search-forward "\n" nil t)
  868.           (replace-match " "))
  869.         (message (concat "Error: " (buffer-substring 1 (point-max))))
  870.         (sit-for 2))
  871.     (message "")
  872.     (setq did-view t)))
  873.     did-view))
  874.  
  875.  
  876. (defun gnus-uu-call-asynchronous (file-name action)
  877.   "Takes two parameters: The name of the file to be displayed and
  878. the command to display it with. Since the view command is executed
  879. asynchronously, it's kinda hard to decide whether the command succeded
  880. or not, so this function always returns `t'. It also adds \"; rm -f 
  881. file-name\" to the end of the execution string, so the file will be 
  882. removed after viewing has ended."
  883.   (let (command file tmp-file start)
  884.     (while (string-match "/" file-name start)
  885.       (setq start (1+ (match-beginning 0))))
  886.     (setq file (substring file-name start))
  887.     (setq tmp-file (concat gnus-uu-tmp-dir file))
  888.     (if (string= tmp-file file-name)
  889.     ()
  890.       (rename-file file-name tmp-file t)
  891.       (setq file-name tmp-file))
  892.  
  893.     (if (string-match "%s" action)
  894.     (setq command (format action file-name))
  895.       (setq command (concat action " " file-name)))
  896.     (setq command (format "%s ; rm -f %s" command file-name))
  897.     (message (format "Viewing with %s" command))
  898. ;    (sit-for 4)
  899.     (start-process "gnus-uu-view" 
  900.            nil "sh" "-c" command)
  901.     t))
  902.  
  903.  
  904. (defun gnus-uu-decode-and-strip (&optional shar use-marked)
  905.   "This function does all the main work. It finds out what articles
  906. to grab, grabs them, strips the result and decodes. If any of 
  907. these operations fail, it returns `nil', `t' otherwise.
  908. If shar is `t', it will pass this on to gnus-uu-grab-articles
  909. who will (probably) unshar the articles. If use-marked
  910. is non-nil, it won't try to find articles, but use the marked list."
  911.   (let (list-of-articles)
  912.     (save-excursion
  913.  
  914.       (if use-marked
  915.       (progn (if (eq gnus-uu-marked-article-list ())
  916.         (message "No articles marked")
  917.           (setq list-of-articles (reverse gnus-uu-marked-article-list))
  918.           (gnus-uu-unmark-all-articles)))
  919.     (setq list-of-articles (gnus-uu-get-list-of-articles)))
  920.       
  921.       (and list-of-articles
  922.        (gnus-uu-grab-articles list-of-articles 
  923.                   (if shar 
  924.                       'gnus-uu-unshar-article
  925.                     'gnus-uu-uustrip-article-as))))))
  926.  
  927.  
  928. (defun gnus-uu-reginize-string (string)
  929.   "Takes a string and puts a \\ in front of every special character;
  930. ignores any leading \"version numbers\"
  931. thingies that they use in the comp.binaries groups, and either replaces
  932. anything that looks like \"2/3\" with \"[0-9]+/[0-9]+\" or, if it can't find
  933. something like that, replaces the last two numbers with \"[0-9]+\". This,
  934. in my experience, should get most postings of a series." 
  935.   (let ((count 2)
  936.     reg)
  937.     (save-excursion
  938.       (set-buffer (get-buffer-create gnus-uu-output-buffer-name))
  939.       (erase-buffer)
  940.       (insert string)
  941.  
  942.       (goto-char 1)
  943.       (while (re-search-forward "[\\[\\^\\+\\\\\\?\\$\\.\\*]" nil t)
  944.     (backward-char)
  945.     (insert "\\")
  946.     (forward-char))
  947.  
  948.       (goto-char 1)
  949.       (if (looking-at "[a-z][a-zA-Z0-9]*: ?")
  950.       (replace-match "[a-z][a-zA-Z0-9]*: ?" nil nil))
  951.  
  952.       (goto-char 1)
  953.       (while (re-search-forward "[ \t]+" nil t)
  954.     (replace-match "[ \\t]+"))
  955.  
  956.       (goto-char 1)
  957.       (if (re-search-forward "[0-9]+/[0-9]+" nil t)
  958.       (replace-match "[0-9]+/[0-9]+")
  959.  
  960.     (goto-char 1)
  961.     (if (re-search-forward "[0-9]+ *of *[0-9]+" nil t)
  962.         (replace-match "[0-9]+ *of *[0-9]+")
  963.  
  964.       (end-of-line)
  965.       (while (and (re-search-backward "[0-9]" nil t) (> count 0))
  966.             (while (looking-at "[0-9]")
  967.               (backward-char))
  968.             (re-search-forward "[0-9]+" nil t)
  969.         (replace-match "[0-9]+")
  970.         (backward-char 5)
  971.         (setq count (1- count)))))
  972. ;      (message (format "reg er %s" (buffer-substring 1 (point-max))))
  973. ;      (sit-for 4)
  974.       (buffer-substring 1 (point-max)))))
  975.  
  976.  
  977. (defun gnus-uu-get-list-of-articles (&optional subject mark-articles only-unread)
  978.   "Finds all articles that matches the regular expression given.
  979. Returns the resulting list."
  980.   (let (beg end reg-subject list-of-subjects list-of-numbers art-num)
  981.     (save-excursion
  982.       
  983. ; If the subject is not given, this function looks at the current subject
  984. ; and takes that.
  985.  
  986.       (if subject
  987.       (setq reg-subject subject)
  988.     (end-of-line)
  989.     (setq end (point))
  990.     (beginning-of-line)
  991.     (if (not (re-search-forward "\\] " end t))
  992.         (progn (message "No valid subject chosen") (sit-for 2))
  993.       (setq subject (buffer-substring (point) end))
  994.       (setq reg-subject (concat
  995.                  "\\[.*\\] " 
  996.                  (gnus-uu-reginize-string subject)))))
  997.  
  998.       (if reg-subject
  999.       (progn
  1000.  
  1001. ; Collect all subjects matching reg-subject.
  1002.  
  1003.         (goto-char 1)
  1004.         (while (re-search-forward reg-subject nil t)
  1005.           (beginning-of-line)
  1006.           (setq beg (point))
  1007.           (if (or (not only-unread) (looking-at " \\|-"))
  1008.           (progn
  1009.             (end-of-line)
  1010.             (setq list-of-subjects (cons (buffer-substring beg (point))
  1011.                          list-of-subjects)))
  1012.         (end-of-line)))
  1013.         
  1014.         
  1015. ; Expand all numbers in all the subjects: (hi9 -> hi0009, etc).
  1016.  
  1017.         (setq list-of-subjects (gnus-uu-expand-numbers list-of-subjects))
  1018.  
  1019. ; Sort the subjects.
  1020.  
  1021.         (setq list-of-subjects (sort list-of-subjects 'gnus-uu-string<))
  1022.  
  1023. ; Get the article numbers from the sorted list of subjects.
  1024.  
  1025.         (while (not (eq list-of-subjects ()))
  1026.           (setq art-num (gnus-uu-article-number (car list-of-subjects)))
  1027.           (if mark-articles (gnus-summary-mark-as-read art-num ?#))
  1028.           (setq list-of-numbers (cons art-num list-of-numbers))
  1029.           (setq list-of-subjects (cdr list-of-subjects)))
  1030.         
  1031.         (setq list-of-numbers (reverse list-of-numbers))
  1032.  
  1033.         (if (eq list-of-numbers ())
  1034.         (progn 
  1035.           (message (concat "No subjects matched " subject))
  1036.           (sit-for 2)))))
  1037.  
  1038.       list-of-numbers)))
  1039.  
  1040.  
  1041. (defun gnus-uu-expand-numbers (string-list)
  1042.   "Takes a list of strings and \"expands\" all numbers in all the strings.
  1043. That is, this function makes all numbers equal length by prepending lots
  1044. of zeroes before each number. This is to ease later sorting to find out
  1045. what sequence the articles are supposed to be decoded in. Returns the list
  1046. of expanded strings."
  1047.   (let (string out-list pos num)
  1048.     (while (not (eq string-list ()))
  1049.       (setq string (car string-list))
  1050.       (setq string-list (cdr string-list))
  1051.       (setq pos (string-match "\\] " string))
  1052.       (while (string-match "\\([^0-9]*\\|^\\)\\([0-9]+\\)\\([^0-9]\\|$\\)"
  1053.                string pos)
  1054.     (setq num (- 6 (- (match-end 2) (match-beginning 2))))
  1055.     (setq string
  1056.           (format "%s%06d%s" 
  1057.               (substring string 0 (match-beginning 2))
  1058.               (string-to-int (substring string
  1059.                            (match-beginning 2)
  1060.                            (match-end 2)))
  1061.               (substring string (match-end 2))))
  1062.     (setq pos (+ (match-end 2) num)))
  1063.       (setq out-list (cons string out-list)))
  1064.     out-list))
  1065.  
  1066.  
  1067. (defun gnus-uu-string< (string1 string2) 
  1068.   "Used in a sort for finding out what string is bigger, but ignoring
  1069. everything before the subject part."
  1070.   (string< (substring string1 (string-match "\\] " string1))
  1071.        (substring string2 (string-match "\\] " string2))))
  1072.  
  1073.  
  1074. ;; gnus-uu-grab-article
  1075. ;;
  1076. ;; This is the general multi-article treatment function. 
  1077. ;; It takes a list of articles to be grabbed and a function
  1078. ;; to apply to each article. It puts the result in 
  1079. ;; gnus-uu-result-buffer.
  1080. ;;
  1081. ;; The function to be called should take two parameters.
  1082. ;; The first is the buffer that has the article that should
  1083. ;; be treated. The function should leave the result in this
  1084. ;; buffer as well. This result is then appended on to the
  1085. ;; gnus-uu-result-buffer.
  1086. ;; The second parameter is the state of the list of articles,
  1087. ;; and can have three values: 'start, 'middle and 'end.
  1088. ;; The function can have several return values. 
  1089. ;; 'error if there was an error while treating.
  1090. ;; 'end if the last article has been sighted.
  1091. ;; 'begin-and-end if the article is both the beginning and
  1092. ;;   the end. All these three return values results in 
  1093. ;;   gnus-uu-grab-articles stopping traversing of the list
  1094. ;;   of articles.
  1095. ;; 'middle if the article is a "middle" article.
  1096. ;; 'ok if everything is ok.
  1097.  
  1098. (defvar gnus-uu-has-been-grabbed nil)
  1099.  
  1100. (defun gnus-uu-unmark-list-of-grabbed (&optional dont-unmark-last-article)
  1101.   (let (art)
  1102.     (if (or (not gnus-uu-has-been-grabbed) 
  1103.         (not gnus-uu-unmark-articles-not-decoded))
  1104.     ()
  1105.       (if dont-unmark-last-article
  1106.       (progn
  1107.         (setq art (car gnus-uu-has-been-grabbed))
  1108.         (setq gnus-uu-has-been-grabbed (cdr gnus-uu-has-been-grabbed))))
  1109.       (while gnus-uu-has-been-grabbed
  1110.     (gnus-summary-mark-as-unread (car gnus-uu-has-been-grabbed) t)
  1111.     (setq gnus-uu-has-been-grabbed (cdr gnus-uu-has-been-grabbed)))
  1112.       (if dont-unmark-last-article
  1113.       (setq gnus-uu-has-been-grabbed (list art)))
  1114.       )))
  1115.  
  1116.  
  1117. (defun gnus-uu-grab-articles (list-of-articles process-function)
  1118.   "This function takes a list of articles and a function to apply 
  1119. to each article grabbed. The result of the function is appended
  1120. on to gnus-uu-result-buffer. 
  1121.  
  1122. This function returns `t' if the grabbing and the process-function
  1123. has been successful and `nil' otherwise."
  1124.   (let ((result-buffer (get-buffer-create gnus-uu-result-buffer))
  1125.     (state 'first)
  1126.     (process-state 'ok)
  1127.     (result t)
  1128.     (wrong-type t)
  1129.     (has-been-begin nil)
  1130.     (article nil))
  1131.  
  1132.     (save-excursion
  1133.       (set-buffer result-buffer)
  1134.       (erase-buffer))
  1135.     (setq gnus-uu-has-been-grabbed nil)
  1136.     (while (and (not (eq list-of-articles ())) 
  1137.         (not (eq process-state 'end))
  1138.         (not (eq process-state 'begin-and-end))
  1139.         (not (eq process-state 'error)))
  1140.       (setq article (car list-of-articles))
  1141.       (setq list-of-articles (cdr list-of-articles))
  1142.       (setq gnus-uu-has-been-grabbed (cons article gnus-uu-has-been-grabbed))
  1143.  
  1144.       (if (eq list-of-articles ()) (setq state 'last))
  1145.  
  1146.       (message (format "Getting article %d" article))
  1147. ;      (sit-for 2)
  1148.       (if (not (= (or gnus-current-article 0) article))
  1149.       (gnus-summary-display-article article))
  1150.       (gnus-summary-mark-as-read article)
  1151.  
  1152.       (save-excursion 
  1153.     (set-buffer gnus-article-buffer)
  1154.     (widen))
  1155.  
  1156.       (setq process-state (funcall process-function gnus-article-buffer state))
  1157.  
  1158.       (if (eq process-state 'begin)
  1159.       (setq has-been-begin t))
  1160.  
  1161.       (if (not (eq process-state 'wrong-type))
  1162.       (setq wrong-type nil)
  1163.     (if gnus-uu-unmark-articles-not-decoded
  1164.         (gnus-summary-mark-as-unread article t)))
  1165.  
  1166.       (if gnus-uu-do-sloppy-uudecode
  1167.       (setq wrong-type nil))
  1168.  
  1169.       (if (and (not has-been-begin)
  1170.            (not gnus-uu-do-sloppy-uudecode)
  1171.            (or (eq process-state 'end)
  1172.            (eq process-state 'middle)))
  1173.       (progn
  1174.         (setq process-state 'error)
  1175.         (message "No begin part at the beginning")
  1176.         (sit-for 2))
  1177.     (setq state 'middle)))
  1178.  
  1179.     (if (and wrong-type (not gnus-uu-do-sloppy-uudecode))
  1180.     (progn
  1181.       (setq result nil)
  1182.       (message "Wrong type file")
  1183.       (sit-for 2))
  1184.       (if (eq process-state 'error)
  1185.       (setq result nil)
  1186.     (if (not (or (eq process-state 'ok) 
  1187.              (eq process-state 'end)
  1188.              (eq process-state 'begin-and-end)))
  1189.         (progn
  1190.           (if (not gnus-uu-do-sloppy-uudecode)
  1191.           (progn
  1192.             (message "End of articles reached before end of file")
  1193.             (sit-for 2)))
  1194.           (gnus-uu-unmark-list-of-grabbed)
  1195.           (setq result nil)))))
  1196.     (setq gnus-uu-rest-of-articles list-of-articles)
  1197.     result))
  1198.  
  1199. (defun gnus-uu-uustrip-article-as (process-buffer in-state)
  1200.   (let ((state 'ok)
  1201.     (process-connection-type nil)
  1202.     start-char pst)
  1203.     (save-excursion
  1204.       (set-buffer process-buffer)
  1205.  
  1206.       (goto-char 1)
  1207.  
  1208.       (if gnus-uu-kill-carriage-return
  1209.       (progn
  1210.         (while (re-search-forward "
  1211. " nil t)
  1212.           (replace-match ""))
  1213.         (goto-char 1)))
  1214.  
  1215.       (if (not (re-search-forward 
  1216.         (concat gnus-uu-begin-string "\\|" gnus-uu-body-line) nil t))
  1217.         (setq state 'wrong-type)
  1218.      
  1219.     (beginning-of-line)
  1220.     (setq start-char (point))
  1221.  
  1222.     (if (looking-at gnus-uu-begin-string)
  1223.         (progn 
  1224.           (setq gnus-uu-file-name 
  1225.             (buffer-substring (match-beginning 1) (match-end 1)))
  1226.           (setq pst (process-status (or gnus-uu-uudecode-process "")))
  1227.           (if (or (eq pst 'stop)
  1228.               (eq pst 'run))
  1229.           (progn
  1230.             (delete-process gnus-uu-uudecode-process)
  1231.             (gnus-uu-unmark-list-of-grabbed t)))
  1232.           (setq gnus-uu-uudecode-process
  1233.             (start-process 
  1234.              "*uudecode*" 
  1235.              (get-buffer-create gnus-uu-output-buffer-name)
  1236.              "sh" "-c" 
  1237.              (format "cd %s ; uudecode" gnus-uu-tmp-dir)))
  1238.           (setq state 'begin)
  1239.           (setq gnus-uu-generated-file-list 
  1240.             (cons (concat gnus-uu-tmp-dir gnus-uu-file-name) 
  1241.               gnus-uu-generated-file-list)))
  1242.       (setq state 'middle))
  1243.     
  1244.     (goto-char (point-max))
  1245.     (re-search-backward 
  1246.      (concat gnus-uu-body-line "\\|" gnus-uu-end-string) nil t)
  1247.     (if (looking-at gnus-uu-end-string)
  1248.         (if (eq state 'begin)
  1249.         (setq state 'begin-and-end)
  1250.           (setq state 'end)))
  1251.     (forward-line 1)
  1252.  
  1253.     (setq pst (process-status (or gnus-uu-uudecode-process "")))
  1254.     (if (or (eq pst 'run) (eq pst 'stop))
  1255.         (process-send-region 
  1256.          gnus-uu-uudecode-process start-char (point))
  1257.       (setq state 'wrong-type))))
  1258.     state))
  1259.  
  1260.  
  1261. (defun gnus-uu-unshar-article (process-buffer in-state)
  1262.   "This function is used by gnus-uu-grab-articles to treat
  1263. a shared article."
  1264.   (let ((state 'ok)
  1265.     start-char)
  1266.     (save-excursion
  1267.      (set-buffer process-buffer)
  1268.      (goto-char 1)
  1269.      (if (not (re-search-forward gnus-uu-shar-begin-string nil t))
  1270.      (setq state 'wrong-type)
  1271.        (beginning-of-line)
  1272.        (setq start-char (point))
  1273.        (call-process-region start-char (point-max) "sh" nil 
  1274.                 (get-buffer-create gnus-uu-output-buffer-name) nil "-c" 
  1275.                 (concat "cd " gnus-uu-shar-directory " ; sh"))))
  1276.     state))
  1277.  
  1278.  
  1279. (defun gnus-uu-find-name-in-shar ()
  1280.   "Returns the name of what the shar file is going to unpack."
  1281.   (let ((oldpoint (point))
  1282.     res)
  1283.     (goto-char 1)
  1284.     (if (re-search-forward gnus-uu-shar-name-marker nil t)
  1285.     (setq res (buffer-substring (match-beginning 1) (match-end 1))))
  1286.     (goto-char oldpoint)
  1287.     res))
  1288.       
  1289.  
  1290. (defun gnus-uu-article-number (subject)
  1291.   "Returns the article number of the given subject."
  1292.   (let (end)
  1293.     (string-match "[0-9]+[^0-9]" subject 1)
  1294.     (setq end (match-end 0))
  1295.     (string-to-int 
  1296.      (substring subject (string-match "[0-9]" subject 1) end)))) 
  1297.           
  1298.  
  1299. (defun gnus-uu-decode (directory)
  1300.   "UUdecodes everything in the buffer and returns the name of the resulting
  1301. file."
  1302.   (let ((command (concat "cd " directory " ; uudecode"))
  1303.     file-name)
  1304.     (save-excursion
  1305.       (message "Uudecoding...")
  1306.       (set-buffer (get-buffer-create gnus-uu-result-buffer))
  1307.       (setq file-name (concat gnus-uu-tmp-dir gnus-uu-file-name))
  1308.       (gnus-uu-add-file file-name)
  1309.       (call-process-region 1 (point-max) "sh" nil t nil "-c" command)
  1310.       file-name)))
  1311.  
  1312.  
  1313. (defun gnus-uu-choose-action (file-name file-action-list)
  1314.   "Chooses what action to perform given the name and gnus-uu-file-action-list.
  1315. Returns either nil if no action is found, or the name of the command
  1316. to run if such a rule is found."
  1317.   (let ((action-list (copy-sequence file-action-list))
  1318.     rule action)
  1319.     (while (not (or (eq action-list ()) action))
  1320.       (setq rule (car action-list))
  1321.       (setq action-list (cdr action-list))
  1322.       (if (string-match (car rule) file-name)
  1323.       (setq action (car (cdr rule)))))
  1324.     action))
  1325.  
  1326.  
  1327. (defun gnus-uu-save-file (from-file-name &optional default-dir ignore-existing)
  1328.   "Moves the file from the tmp directory to where the user wants it."
  1329.   (let (dir file-name command)
  1330.     (string-match "/[^/]*$" from-file-name)
  1331.     (setq file-name (substring from-file-name (1+ (match-beginning 0))))
  1332.     (if default-dir
  1333.     (setq dir default-dir)
  1334.       (setq dir (gnus-uu-read-directory "Where do you want the file? "
  1335.                     gnus-uu-current-save-dir))
  1336.       (setq gnus-uu-current-save-dir dir))
  1337.     (if (and (not ignore-existing) (file-exists-p (concat dir file-name)))
  1338.     (progn
  1339.       (message (concat "There already is a file called " file-name))
  1340.       (sit-for 2)
  1341.       (setq file-name
  1342.         (read-file-name "Give a new name: " dir (concat dir file-name)
  1343.                 nil file-name)))
  1344.       (setq file-name (concat dir file-name)))
  1345.     (rename-file from-file-name file-name t)))
  1346.     
  1347.  
  1348.  
  1349. ;; reading a directory name, and offering to create if it doesn't exist.
  1350. ;; Taken from gnus-mark
  1351.  
  1352. (defun gnus-uu-read-directory (prompt &optional default-dir)
  1353.   (let ((dir
  1354.      (read-file-name prompt
  1355.              (or default-dir default-directory)
  1356.              (or default-dir default-directory))))
  1357.     (if (string-match "/$" dir)
  1358.     (setq dir (substring dir 0 (match-beginning 0))))
  1359.     (setq dir
  1360.       (cond ((file-directory-p dir) dir)
  1361.         ((file-exists-p dir)
  1362.          (ding)
  1363.          (message "%s exists and is not a directory!" dir)
  1364.          (sleep-for 2)
  1365.          (gnus-uu-read-directory prompt dir))
  1366.         ((y-or-n-p (format "directory %s doesn't exist, create it? " dir))
  1367.          (make-directory dir)
  1368.          dir)
  1369.         (t (gnus-uu-read-directory prompt dir))))
  1370.     (if (string-match "/$" dir)
  1371.     dir
  1372.       (concat dir "/"))))
  1373.  
  1374.  
  1375. (defun gnus-uu-treat-archive (file-name)
  1376.   "Unpacks an archive and views all the files in it. Returns `t' if
  1377. viewing one or more files is successful."
  1378.   (let ((arc-dir (make-temp-name 
  1379.           (concat gnus-uu-tmp-dir "gnusuu")))
  1380.     action command files file did-view short-file-name
  1381.     error-during-unarching)
  1382.     (setq action (gnus-uu-choose-action 
  1383.           file-name (append gnus-uu-user-archive-rules
  1384.                     (if gnus-uu-ignore-default-archive-rules
  1385.                     nil
  1386.                       gnus-uu-default-archive-rules))))
  1387.     (if (not action)
  1388.     (progn (message (format "No unpackers for the file %s" file-name))
  1389.            (sit-for 2))
  1390.       (string-match "/[^/]*$" file-name)
  1391.       (setq short-file-name (substring file-name (1+ (match-beginning 0))))
  1392.       (setq command (format "mv %s %s ; cd %s ; %s %s " 
  1393.                 file-name arc-dir 
  1394.                 arc-dir 
  1395.                 action short-file-name ))
  1396.       (make-directory arc-dir)
  1397.       (setq gnus-uu-generated-file-list 
  1398.         (cons arc-dir gnus-uu-generated-file-list))
  1399.  
  1400.       (save-excursion
  1401.     (set-buffer (get-buffer-create gnus-uu-output-buffer-name))
  1402.     (erase-buffer))
  1403.  
  1404.       (message (format "Unpacking with %s..." action))
  1405.  
  1406.       (if (= 0 (call-process "sh" nil 
  1407.                  (get-buffer-create gnus-uu-output-buffer-name)
  1408.                  nil "-c" command))
  1409.       (message "")
  1410.     (message "Error during unpacking of archive")
  1411.     (sit-for 2)
  1412.     (sit-for 2)
  1413.     (setq error-during-unarching t))
  1414.  
  1415.       (call-process "sh" nil (get-buffer gnus-uu-output-buffer-name)
  1416.             nil "-c" (format "mv %s/%s %s" arc-dir short-file-name
  1417.                      gnus-uu-tmp-dir))
  1418.     
  1419.       (setq did-view (or (gnus-uu-show-directory 
  1420.               arc-dir gnus-uu-use-interactive-view) did-view))
  1421.  
  1422.       (if (and (not gnus-uu-use-interactive-view) 
  1423.            (file-directory-p arc-dir))
  1424.       (delete-directory arc-dir)))
  1425.  
  1426.     did-view))
  1427.  
  1428.  
  1429. (defun gnus-uu-show-directory (dir &optional dont-delete-files)
  1430.   "Tries to view all the files in the given directory. Returns `t' if
  1431. viewing one or more files is successful."
  1432.   (let (files file did-view)
  1433.     (setq files (directory-files dir t))
  1434.     (setq gnus-uu-generated-file-list
  1435.       (append files gnus-uu-generated-file-list))
  1436.     (while (not (eq files ()))
  1437.       (setq file (car files))
  1438.       (setq files (cdr files))
  1439.       (if (and (not (string-match "/\\.$" file)) 
  1440.            (not (string-match "/\\.\\.$" file)))
  1441.       (progn
  1442.         (if (file-directory-p file)
  1443.         (setq did-view (or (gnus-uu-show-directory file 
  1444.                                dont-delete-files) 
  1445.                    did-view))
  1446.           (setq did-view (or (gnus-uu-view-file file t) did-view))
  1447.           (if (and (not dont-delete-files) (file-exists-p file)) 
  1448.                (delete-file file))))))
  1449.     (if (not dont-delete-files) (delete-directory dir))
  1450.     did-view))
  1451.  
  1452. ;; Manual choosing stuff
  1453.  
  1454. (defun gnus-uu-enter-mark-in-list ()
  1455.   (let (article    beg)
  1456.     (beginning-of-line)
  1457.     (setq beg (point))
  1458.     (end-of-line)
  1459.     (setq article (gnus-uu-article-number 
  1460.            (buffer-substring beg (point))))
  1461.     (message (format "Adding article %d to list" article))
  1462.     (setq gnus-uu-marked-article-list 
  1463.       (cons article gnus-uu-marked-article-list)))) 
  1464.  
  1465. (defun gnus-uu-mark-article ()
  1466.   "Marks the current article to be decoded later."
  1467.   (interactive)
  1468.   (gnus-uu-enter-mark-in-list)
  1469.   (gnus-summary-mark-as-read nil ?#)
  1470.   (gnus-summary-next-subject 1 nil))
  1471.  
  1472. (defun gnus-uu-unmark-article ()
  1473.   "Unmarks the current article."
  1474.   (interactive)
  1475.   (let ((in (copy-sequence gnus-uu-marked-article-list))
  1476.     out article beg found
  1477.     (old-point (point)))
  1478.     (beginning-of-line)
  1479.       (setq beg (point))
  1480.       (end-of-line)
  1481.       (setq article (gnus-uu-article-number (buffer-substring beg (point))))
  1482.       (message (format "Removing article %d" article))
  1483.       (while (not (eq in ()))
  1484.     (if (not (= (car in) article))
  1485.         (setq out (cons (car in) out))
  1486.       (setq found t)
  1487.       (message (format "Removing article %d" article)))
  1488.     (setq in (cdr in)))
  1489.       (if (not found) (message "Not a marked article."))
  1490.       (setq gnus-uu-marked-article-list (reverse out))
  1491.       (gnus-summary-mark-as-unread nil t)
  1492.       (gnus-summary-next-subject 1 nil)))
  1493.     
  1494.  
  1495. (defun gnus-uu-unmark-all-articles ()
  1496.   "Removes the mark from all articles marked for decoding."
  1497.   (interactive)
  1498.   (let ((articles (copy-sequence gnus-uu-marked-article-list)))
  1499.     (while (not (eq articles ()))
  1500.       (gnus-summary-goto-subject (car articles))
  1501.       (gnus-summary-mark-as-unread nil t)
  1502.       (setq articles (cdr articles)))
  1503.     (setq gnus-uu-marked-article-list ())
  1504.   ))
  1505.  
  1506.       
  1507.  
  1508.  
  1509. (defun gnus-uu-mark-by-regexp ()
  1510.   "Asks for a regular expression and marks all articles that match for later decoding."
  1511.   (interactive)
  1512.   (let (exp)
  1513.     (setq exp (read-from-minibuffer "Enter regular expression: "))
  1514.     (setq gnus-uu-marked-article-list 
  1515.       (reverse (gnus-uu-get-list-of-articles exp t)))
  1516.     (message "")))
  1517.       
  1518.  
  1519. ;; Various
  1520.  
  1521. (defun gnus-uu-initialize ()
  1522.   (if (not gnus-uu-use-interactive-view)
  1523.       ()
  1524.     (save-excursion
  1525.       (setq gnus-uu-interactive-file-list nil)
  1526.       (set-buffer (get-buffer-create gnus-uu-interactive-buffer-name))
  1527.       (erase-buffer)
  1528.       (gnus-uu-mode)
  1529.       (insert 
  1530.        "# Press return to execute a command.
  1531. # Press `C-c C-c' to exit interactive view.
  1532.  
  1533. ")
  1534.       )))
  1535.  
  1536. (defun gnus-uu-clean-up ()
  1537.   "Kills the temporary uu buffers."
  1538.   (let (buf pst)
  1539.     (setq gnus-uu-do-sloppy-uudecode nil)
  1540.     (setq pst (process-status (or gnus-uu-uudecode-process "")))
  1541.     (if (or (eq pst 'stop)
  1542.         (eq pst 'run))
  1543.     (delete-process gnus-uu-uudecode-process))
  1544.     (and (setq buf (get-buffer gnus-uu-output-buffer-name))
  1545.      (kill-buffer buf))
  1546.     (and (setq buf (get-buffer gnus-uu-result-buffer))
  1547.      (kill-buffer buf))))
  1548.  
  1549.  
  1550. (defun gnus-uu-check-for-generated-files ()
  1551.   "Deletes any generated files that hasn't been deleted, if, for
  1552. instance, the user terminated decoding with `C-g'."
  1553.   (let (file)
  1554.     (while (not (eq gnus-uu-generated-file-list ()))
  1555.       (setq file (car gnus-uu-generated-file-list))
  1556.       (setq gnus-uu-generated-file-list (cdr gnus-uu-generated-file-list))
  1557.       (if (not (string-match "/\\.[\\.]?" file))
  1558.       (progn
  1559.         (if (file-directory-p file)
  1560.         (delete-directory file)
  1561.           (if (file-exists-p file)
  1562.           (delete-file file))))))))
  1563.  
  1564. (defun gnus-uu-get-current-dir (&optional prompt)
  1565.   (setq gnus-uu-current-save-dir 
  1566.     (gnus-uu-read-directory 
  1567.      (if prompt prompt "Where do you want the file? ")
  1568.      gnus-uu-current-save-dir)))
  1569.  
  1570. (defun gnus-uu-add-file (file)
  1571.   (setq gnus-uu-generated-file-list 
  1572.     (cons file gnus-uu-generated-file-list)))
  1573.  
  1574.  
  1575. ;; Initializing
  1576.  
  1577.  
  1578. (add-hook 'gnus-exit-group-hook
  1579.       '(lambda ()
  1580.      (gnus-uu-clean-up)
  1581.      (setq gnus-uu-marked-article-list nil)
  1582.      (gnus-uu-check-for-generated-files)))
  1583.  
  1584. (let (i)
  1585.   (setq gnus-uu-body-line "^M")
  1586.   (setq i 61)
  1587.   (while (> i 0)
  1588.     (setq gnus-uu-body-line (concat gnus-uu-body-line "."))
  1589.     (setq i (1- i)))
  1590.   (setq gnus-uu-body-line (concat gnus-uu-body-line "?$")))
  1591.  
  1592.  
  1593.  
  1594. ;; Interactive exec mode
  1595.  
  1596. (defvar gnus-uu-output-window nil)
  1597.  
  1598. (defun gnus-uu-do-interactive ()
  1599.   (let (int-buffer out-buf)
  1600.     (set-buffer 
  1601.      (setq int-buffer (get-buffer gnus-uu-interactive-buffer-name)))
  1602.     (switch-to-buffer-other-window int-buffer)
  1603.     (pop-to-buffer int-buffer)
  1604.     (setq gnus-uu-output-window 
  1605.       (split-window nil (- (window-height) gnus-uu-output-window-height)))
  1606.     (set-window-buffer gnus-uu-output-window
  1607.                (setq out-buf 
  1608.                  (get-buffer-create gnus-uu-output-buffer-name)))
  1609.     (save-excursion (set-buffer out-buf) (erase-buffer))
  1610.     (goto-char 1)
  1611.     (forward-line 3)))
  1612.  
  1613. (defun gnus-uu-enter-interactive-file (action file)
  1614.   (let (command)
  1615.     (save-excursion
  1616.       (setq gnus-uu-interactive-file-list
  1617.         (cons file gnus-uu-interactive-file-list))
  1618.       (set-buffer (get-buffer gnus-uu-interactive-buffer-name))
  1619.       (if (string-match "%s" action)
  1620.       (setq command (format action file))
  1621.     (setq command (concat action " " file)))
  1622.  
  1623.       (insert (format "%s\n" command)))))
  1624.  
  1625. (defun gnus-uu-interactive-execute ()
  1626.   (interactive)
  1627.   (let (beg out-buf command)
  1628.     (beginning-of-line)
  1629.     (setq beg (point))
  1630.     (end-of-line)
  1631.     (setq command (buffer-substring beg (point)))
  1632.     (setq out-buf (get-buffer-create gnus-uu-output-buffer-name))
  1633.     (save-excursion
  1634.       (set-buffer out-buf)
  1635.       (erase-buffer)
  1636.       (insert (format "$ %s \n" command)))
  1637.     (message "Executing...")
  1638.     (if gnus-uu-asynchronous
  1639.     (start-process "gnus-uu-view" out-buf "sh" "-c" command)
  1640.       (call-process "sh" nil out-buf nil "-c" command)
  1641.       (message ""))
  1642.     (forward-line 1)
  1643.     (beginning-of-line)
  1644.     ))
  1645.  
  1646. (defconst gnus-uu-mode-map nil "")
  1647.  
  1648. (defun gnus-uu-interactive-end ()
  1649.   "This function ends interactive view mode and returns to summary mode."
  1650.   (interactive)
  1651.   (let (buf)
  1652.     (delete-window gnus-uu-output-window)
  1653.     (gnus-uu-clean-up)
  1654.     (gnus-uu-check-for-generated-files)
  1655.     (setq buf (get-buffer gnus-uu-interactive-buffer-name))
  1656.     (if gnus-article-buffer (switch-to-buffer gnus-article-buffer))
  1657.     (if buf (kill-buffer buf))
  1658.     (pop-to-buffer gnus-summary-buffer)))
  1659.  
  1660. (if gnus-uu-mode-map
  1661.     ()
  1662.   (setq gnus-uu-mode-map (make-sparse-keymap))
  1663.   (define-key gnus-uu-mode-map "\C-c\C-x" 'gnus-uu-interactive-execute)
  1664.   (define-key gnus-uu-mode-map "\C-c\C-v" 'gnus-uu-interactive-execute)
  1665.   (define-key gnus-uu-mode-map "\C-m" 'gnus-uu-interactive-execute)
  1666.   (define-key gnus-uu-mode-map "\C-c\C-c" 'gnus-uu-interactive-end)
  1667.   (define-key gnus-uu-mode-map "\C-cs" 
  1668.     'gnus-uu-interactive-save-current-file)
  1669.   (define-key gnus-uu-mode-map "\C-c\C-s"
  1670.     'gnus-uu-interactive-save-current-file-silent)
  1671.   (define-key gnus-uu-mode-map "\C-c\C-w" 'gnus-uu-interactive-save-all-files)
  1672.   (define-key gnus-uu-mode-map "\C-c\C-o" 'gnus-uu-interactive-save-original-file)
  1673.   )
  1674.  
  1675. (defun gnus-uu-interactive-save-original-file ()
  1676.   (interactive)
  1677.   (let (file)
  1678.     (if (file-exists-p 
  1679.      (setq file (concat gnus-uu-tmp-dir
  1680.                 (or gnus-uu-file-name gnus-uu-shar-file-name))))
  1681.     (gnus-uu-save-file file)
  1682.       (message "Already saved."))))
  1683.  
  1684.  
  1685. (defun gnus-uu-interactive-save-current-file-silent ()
  1686.   "hei"
  1687.   (interactive)
  1688.   (gnus-uu-interactive-save-current-file t))
  1689.  
  1690. (defun gnus-uu-interactive-save-current-file (&optional dont-ask silent)
  1691.   "Saves the file referred to on the current line."
  1692.   (interactive)
  1693.   (let (files beg line file)
  1694.     (setq files (copy-sequence gnus-uu-interactive-file-list))
  1695.     (beginning-of-line)
  1696.     (setq beg (point))
  1697.     (end-of-line)
  1698.     (setq line (buffer-substring beg (point)))
  1699.     (while (and files
  1700.         (not (string-match 
  1701.               (concat "" (regexp-quote (setq file (car files))) "")
  1702.               line)))
  1703.       (setq files (cdr files)))
  1704.     (beginning-of-line)
  1705.     (forward-line 1)
  1706.     (if (not files)
  1707.     (if (not silent)
  1708.         (progn (message "Could not find file") (sit-for 2)))
  1709.       (gnus-uu-save-file file (if dont-ask gnus-uu-current-save-dir nil) silent)
  1710.       (delete-region beg (point)))))
  1711.  
  1712.  
  1713. (defun gnus-uu-interactive-save-all-files ()
  1714.   "Saves all files referred to on the current line."
  1715.   (interactive)
  1716.   (let (dir)
  1717.     (goto-char 1)
  1718.     (setq dir (gnus-uu-get-current-dir "Where do you want the files? "))
  1719.     (while (not (eobp))
  1720.       (gnus-uu-interactive-save-current-file t t))))
  1721.  
  1722.     
  1723.  
  1724.  
  1725. (defun gnus-uu-mode ()
  1726.   "Major mode for editing view commands in gnus-uu.
  1727.  
  1728.  
  1729. Commands:
  1730. Return, C-c C-v, C-c C-x        Execute the current command
  1731. C-c C-c                         End interactive mode
  1732. C-c s                           Save the current file
  1733. C-c C-s                         Save the current file without asking 
  1734.                                 where to put it
  1735. C-c C-a                         Save all files
  1736. C-c C-o                         Save the original file: If the files
  1737.                                 originated in an archive, the archive 
  1738.                                 file is saved.
  1739. "
  1740.   (interactive)
  1741.   (kill-all-local-variables)
  1742.   (use-local-map gnus-uu-mode-map)   
  1743.   (setq mode-name "gnus-uu")         
  1744.   (setq major-mode 'gnus-uu-mode)    
  1745. )
  1746.  
  1747.   (define-key gnus-uu-mode-map "\C-c\C-x" 'gnus-uu-interactive-execute)
  1748.   (define-key gnus-uu-mode-map "\C-c\C-v" 'gnus-uu-interactive-execute)
  1749.   (define-key gnus-uu-mode-map "\C-m" 'gnus-uu-interactive-execute)
  1750.   (define-key gnus-uu-mode-map "\C-c\C-c" 'gnus-uu-interactive-end)
  1751.   (define-key gnus-uu-mode-map "\C-cs" 
  1752.     'gnus-uu-interactive-save-current-file)
  1753.   (define-key gnus-uu-mode-map "\C-c\C-s"
  1754.     'gnus-uu-interactive-save-current-file-silent)
  1755.   (define-key gnus-uu-mode-map "\C-c\C-a" 'gnus-uu-interactive-save-all-files)
  1756.   (define-key gnus-uu-mode-map "\C-c\C-o" 'gnus-uu-interactive-save-original-file)
  1757.  
  1758. (provide 'gnus-uu)
  1759.